home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
IO CD February 1999
/
IO_LUTY_99.ISO
/
DODATKI
/
Brood War
/
GREETBOT.ZIP
/
BNBOT.CPP
next >
Wrap
C/C++ Source or Header
|
1998-03-31
|
13KB
|
533 lines
//
// BNBOT.CPP
//
// Implementation of a virtual base class for Battle.net bots.
//
// by Scott Coleman 3/31/98
//
//
#include "pch.h"
#pragma hdrstop
#define BUFSIZE 2048
// event IDs
#define EID_SHOWUSER 1001
#define EID_JOIN 1002
#define EID_LEAVE 1003
#define EID_WHISPER 1004
#define EID_TALK 1005
#define EID_BROADCAST 1006
#define EID_CHANNEL 1007
#define EID_USERFLAGS 1009
#define EID_WHISPERSENT 1010
#define EID_CHANNELFULL 1013
#define EID_CHANNELDOESNOTEXIST 1014
#define EID_CHANNELRESTRICTED 1015
#define EID_INFO 1018
#define EID_ERROR 1019
#define EID_EMOTE 1023
#define EID_UNIQUENAME 2010
//============================================================================
BnBot::BnBot() {
log = 0;
s = INVALID_SOCKET;
nServerPort = 6112;
szLoginName[0] = '\0';
szUniqueName[0] = '\0';
szPassword[0] = '\0';
szServerAddr[0] = '\0';
szHomeChannel[0] = '\0';
szCurrentChannel[0] = '\0';
}
//============================================================================
BnBot::~BnBot() {
LogClose();
}
//============================================================================
void BnBot::SetLogonInfo(char *szUserName,
char *szUserPass,
char *szServer,
short nPort) {
strcpy(szLoginName, szUserName);
strcpy(szUniqueName, szUserName);
strcpy(szPassword, szUserPass);
strcpy(szServerAddr, szServer);
nServerPort = nPort;
}
//============================================================================
void BnBot::SetHomeChannel(char *szChannelName) {
strcpy(szHomeChannel, szChannelName);
}
//============================================================================
int BnBot::Connect() {
struct sockaddr_in name;
struct hostent *hp;
memset(&name, '\0', sizeof(name));
name.sin_family = AF_INET;
name.sin_port = htons(nServerPort);
// if this is a hostname and not an IP address, resolve it
char *p = szServerAddr;
while (*p && (isdigit(*p) || (*p == '.'))) {
p++;
}
// non-digit found - assume hostname
if (*p) {
hp = gethostbyname(szServerAddr);
if (hp == 0)
return 0; // can't resolve hostname
memcpy(&name.sin_addr, hp->h_addr, hp->h_length);
}
else {
name.sin_addr.s_addr = inet_addr(szServerAddr);
}
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET) {
return 0;
}
if (connect(s, (struct sockaddr *)&name, sizeof(name))) {
return 0;
}
return 1;
}
//============================================================================
int BnBot::Logon() {
// send ^C, ^D, username, and password
// ^C gets the server's attention for logon; ^D turns off ECHO
Send("%c%c%s\r\n%s\r\n", 0x03, 0x04, szLoginName, szPassword);
return 1;
}
//============================================================================
void BnBot::Disconnect() {
if (s == INVALID_SOCKET)
return;
closesocket(s);
s = INVALID_SOCKET;
}
//============================================================================
int BnBot::Reconnect() {
LogWrite("Attempting to connect...");
for (int tries=0; tries < 10; ++tries) {
if (!Connect()) {
LogWrite("Connect() failed.");
Sleep(5000);
continue;
}
if (!Logon()) {
LogWrite("Logon() failed.");
continue;
}
Sleep(1000);
Send("/join %s\r\n", szHomeChannel);
return 1;
}
LogWrite("Unable to log on after %d tries - giving up.", tries);
return 0;
}
//============================================================================
int __cdecl BnBot::Send(char *lpszFmt, ...) {
char szOutStr[MAXTEXTLENGTH];
va_list argptr;
va_start(argptr, lpszFmt);
vsprintf(szOutStr, lpszFmt, argptr);
va_end(argptr);
if (send(s, szOutStr, strlen(szOutStr), 0) < 0)
return 0;
return 1;
}
//============================================================================
int BnBot::ParseEvent(char *pszEvent,
int *pnEventId,
char *pszSpeaker,
u_long *puFlags,
char *pszEventText) {
if (!pszEvent || !pnEventId || !pszSpeaker || !puFlags || !pszEventText)
return 1;
*pszSpeaker = '\0';
*pszEventText = '\0';
*puFlags = 0;
*pnEventId = atoi(pszEvent);
// some event messages have no speaker or flag fields
if ((*pnEventId != EID_INFO) && (*pnEventId != EID_CHANNELFULL) &&
(*pnEventId != EID_CHANNEL) &&
(*pnEventId != EID_CHANNELDOESNOTEXIST) &&
(*pnEventId != EID_CHANNELRESTRICTED) && (*pnEventId != EID_ERROR)) {
char szJunk[MAXSTRINGLENGTH];
sscanf(pszEvent, "%d %s %s %x", pnEventId, szJunk, pszSpeaker, puFlags);
}
// the event text is enclosed in quotes
char *p = strchr(pszEvent, '"');
if (p) {
strncpy(pszEventText, p+1, MAXTEXTLENGTH);
pszEventText[MAXTEXTLENGTH-1] = '\0';
// nix the trailing quote
p = strrchr(pszEventText, '"');
if (p)
*p = '\0';
}
return 1;
}
//============================================================================
int BnBot::Dispatch(char *szEventMsg) {
int nEventId;
u_long uFlags;
char szSpeaker[MAXSTRINGLENGTH] = "";
char szEventText[MAXTEXTLENGTH] = "";
if (!ParseEvent(szEventMsg,
&nEventId,
szSpeaker,
&uFlags,
szEventText)) {
return 0;
}
// dispatch to the appropriate event handler
switch (nEventId) {
case EID_SHOWUSER:
OnShowUser(szSpeaker, uFlags, szEventText);
break;
case EID_JOIN:
OnJoin(szSpeaker, uFlags, szEventText);
break;
case EID_USERFLAGS:
OnUserFlags(szSpeaker, uFlags, szEventText);
break;
case EID_LEAVE:
OnLeave(szSpeaker, uFlags, szEventText);
break;
case EID_TALK:
OnTalk(szSpeaker, uFlags, szEventText);
break;
case EID_BROADCAST:
OnBroadcast(szSpeaker, uFlags, szEventText);
break;
case EID_CHANNEL:
OnChannel(szSpeaker, uFlags, szEventText);
break;
case EID_WHISPER:
OnWhisper(szSpeaker, uFlags, szEventText);
break;
case EID_WHISPERSENT:
OnWhisperSent(szSpeaker, uFlags, szEventText);
break;
case EID_EMOTE:
OnEmote(szSpeaker, uFlags, szEventText);
break;
case EID_CHANNELFULL:
OnChannelFull(szSpeaker, uFlags, szEventText);
break;
case EID_CHANNELDOESNOTEXIST:
OnChannelDoesNotExist(szSpeaker, uFlags, szEventText);
break;
case EID_CHANNELRESTRICTED:
OnChannelRestricted(szSpeaker, uFlags, szEventText);
break;
case EID_INFO:
OnInfo(szSpeaker, uFlags, szEventText);
break;
case EID_ERROR:
OnError(szSpeaker, uFlags, szEventText);
break;
case EID_UNIQUENAME:
OnUniqueName(szSpeaker, uFlags, szEventText);
break;
default:
LogWrite("Unhandled event ID %d", nEventId);
return 0;
break;
}
return 1;
}
//============================================================================
int BnBot::MsgLoop() {
int nBufLen=0;
int nBufPos=0;
char stageBuf[BUFSIZE];
if (s == INVALID_SOCKET)
return 0;
for (;;) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(s, &fds);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int n = select(s+1, &fds, 0, 0, &tv);
if (n) {
int nNumToRead = BUFSIZE-nBufLen-nBufPos;
if (nNumToRead == 0) {
memmove(stageBuf, stageBuf+nBufPos, nBufLen);
nBufPos = 0;
nNumToRead = BUFSIZE-nBufLen;
}
n = recv(s, stageBuf+nBufPos+nBufLen, nNumToRead, 0);
if (n <= 0) {
LogWrite("recv() returned %d, error code %u", n, GetLastError());
return 0;
}
nBufLen += n;
// dispatch all complete messages in the staging buffer
while (nBufLen > 0) {
char *m = stageBuf+nBufPos;
int nMsgLen=0;
while (nMsgLen < nBufLen) {
if (m[nMsgLen] == '\n')
break;
nMsgLen++;
}
nMsgLen++;
if (nMsgLen > nBufLen)
break;
m[nMsgLen-1] = '\0';
if (isdigit(*m))
Dispatch(m);
nBufLen -= nMsgLen;
nBufPos += nMsgLen;
}
if (!nBufLen)
nBufPos = 0;
}
IdleHook();
}
return 1;
}
//=============================================================================
int BnBot::LogOpen(char *lpszFileName) {
if (log) {
return 0;
}
log = fopen(lpszFileName, "ab");
if (!log)
return 0;
return 1;
}
//=============================================================================
int __cdecl BnBot::LogWrite(char *lpszFmt, ...) {
va_list argptr;
char szOutStr[1024];
if (!log)
return 0;
va_start(argptr, lpszFmt);
vsprintf(szOutStr, lpszFmt, argptr);
va_end(argptr);
fprintf(log, "%s\r\n", szOutStr);
return 1;
}
//=============================================================================
void BnBot::LogClose() {
if (log)
fclose(log);
log = 0;
}
/*****************************************************************************
*
* Virtual Event Handlers
*
******/
//============================================================================
inline int BnBot::OnShowUser(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnJoin(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnUserFlags(char *szSpeaker,
u_long uFlags,
char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnLeave(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnTalk(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnBroadcast(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnChannel(char *szSpeaker, u_long uFlags, char *szEventText) {
strcpy(szCurrentChannel, szEventText);
return 1;
}
//============================================================================
inline int BnBot::OnWhisper(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnWhisperSent(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnEmote(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnChannelFull(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnChannelDoesNotExist(char *szSpeaker, u_long uFlags,
char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnChannelRestricted(char *szSpeaker, u_long uFlags,
char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnInfo(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnError(char *szSpeaker, u_long uFlags, char *szEventText) {
return 1;
}
//============================================================================
inline int BnBot::OnUniqueName(char *szSpeaker, u_long uFlags, char *szEventText) {
strcpy(szUniqueName, szSpeaker);
return 1;
}